package logic

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"iot-base/auth/config"
	"iot-base/auth/db"
	"iot-base/auth/logger"
	Log "iot-base/auth/logger"
	"iot-base/auth/model"
	"iot-base/auth/svc"
	types2 "iot-base/auth/types"
	"iot-base/auth/utils"
	"iot-base/common/cache"
	"strings"
	"time"
)

var (
	IndexData = map[string]string{
		"m_so2":     "so2",
		"m_nox":     "nox",
		"m_co":      "co",
		"m_o3":      "o3",
		"m_pm10":    "pm",
		"m_pm25":    "pm",
		"m_total_N": "Measured value",
		"m_total_P": "Measured value",
		"m_NHN":     "Measured value",
		"m_COD":     "Measured value",
		"m_pH":      "pH",
	}
)

type StationLogic struct {
}

func NewStationLogic() *StationLogic {
	return &StationLogic{}
}

func (l *StationLogic) FindStatingList(userId int64, data types2.ReqStation) (gin.H, error) {
	resp := gin.H{
		"total": 0,
		"list":  make([]interface{}, 0),
	}
	if data.GroupId == 0 || data.GroupId == 1 {

		isAdmin, err := NewUserLogic().IsSysAdmin(userId)
		if err != nil {
			logger.Log.Errorf("NewUserLogic().IsSysAdmin(%v) err:= %v", userId, err)
		}
		if isAdmin {
			return l.adminStatingList(userId, data)
		}
	}
	var groupIds []int64
	//if data.GroupId == 0 {
	//	// 查询用户所有的分组
	//	userGroupModel := model.NewAuthGroupModel()
	//	groupList, err := userGroupModel.GetUserGroup(userId)
	//	if err != nil {
	//		return resp, err
	//	}
	//	// 所在的组ID
	//	groupIds = make([]int64, 0, len(groupList))
	//	for index := range groupList {
	//		groupIds = append(groupIds, groupList[index].ID)
	//	}
	//} else {
	//	groupIds = append(groupIds, data.GroupId)
	//}
	groupIds = append(groupIds, data.GroupId)
	total, err := svc.Dao.TStations.FindGroupStationCount(data.Uuid, data.SName, groupIds)
	if err != nil {
		return resp, err
	}
	list, err := svc.Dao.TStations.FindGroupStationList(groupIds, data.Uuid, data.SName, data.Page, data.Size)
	if err != nil {
		return resp, err
	}
	resp["total"] = total
	resp["list"] = list
	return resp, nil
}
func (l *StationLogic) GetStationType(stationId string) (string, error) {
	key := fmt.Sprintf("StationType:%v", stationId)
	redis := db.NewRedis()
	catalogId, err := redis.Get(key)
	if err == nil {
		return catalogId, nil
	}
	result, err := svc.Dao.TTModel.GetTModelCommByStationId(stationId)
	if errors.Is(err, gorm.ErrRecordNotFound) {
		redis.Set(key, "", time.Hour)
		return "", nil
	}
	if err != nil {
		logger.Log.Errorf("iot.NewTModelModel().GetTModelCommByStationId db err:=%v", err)
		redis.Set(key, "", time.Second*3)
		return "", err
	}
	catalogId = result["catalog_id"].(string)
	redis.Set(key, catalogId, time.Minute*24)
	return catalogId, nil
}

// adminStatingList 管理员管理员.
func (l *StationLogic) adminStatingList(userId int64, data types2.ReqStation) (gin.H, error) {
	resp := gin.H{
		"total": 0,
		"list":  make([]interface{}, 0),
	}
	total, err := svc.Dao.TStations.FindCount(data.Uuid, data.SName)
	if err != nil {
		return resp, err
	}
	list, err := svc.Dao.TStations.FindList(data.Uuid, data.SName, data.Page, data.Size)
	if err != nil {
		return resp, err
	}
	resp["total"] = total
	resp["list"] = list
	return resp, nil
}

// EditGroupStations 编辑设备权限.
func (l *StationLogic) EditGroupStations(groupId int64, stations []string) error {
	m := svc.Dao.TAuthGroupStation
	_, err := m.DelGroupStation(groupId)
	if err != nil {
		return err
	}
	length := len(stations)
	if length == 0 {
		return nil
	}
	groupStation := make([]model.AuthGroupStations, 0, length)
	redis := db.NewRedis()
	for _, id := range stations {
		data := model.AuthGroupStations{
			GroupId:   groupId,
			StationId: id,
		}
		groupStation = append(groupStation, data)
		// 清除 redis 缓存.
		key := fmt.Sprintf(db.KeyAuthGroupStation+"#ByStationId#%v", id)
		redis.Del(key)
	}
	return m.BatchSave(groupStation)
}

// FindGroupStationsByStationId 根据站点ID查询数据.
func (l *StationLogic) FindGroupStationsByStationId(stationId string) ([]model.AuthGroupStations, error) {
	var list []model.AuthGroupStations
	// 查询列表
	key := fmt.Sprintf(db.KeyAuthGroupStation+"#ByStationId#%v", stationId)
	redis := db.NewRedis()
	result, err := redis.Get(key)
	if result != "" {
		err := json.Unmarshal([]byte(result), &list)
		return append([]model.AuthGroupStations{}, list...), err
	}
	list, err = svc.Dao.TAuthGroupStation.GetAuthGroupStationsByStationId(stationId)
	if err != nil {
		logger.Log.Errorf("FindGroupStationsByStationId  err:%v req:%v", err, list)
		return list, err
	}
	b, _ := json.Marshal(list)
	redis.Set(key, string(b), time.Hour)
	return append([]model.AuthGroupStations{}, list...), nil
}

// GetUserStations 查询用户设备.
func (l *StationLogic) GetUserStations(userId int64) ([]model.AuthGroupStations, error) {
	// 查询用户组
	userGroup := NewUserGroupLogic()
	groupLogic := NewGroupLogic()
	groupAll, err := groupLogic.FindAll()
	if err != nil {
		return nil, err
	}
	groupList, err := userGroup.FindUserGroup(userId)
	if err != nil {
		return nil, err
	}
	// 查找字节点.
	list := utils.FindRelationNode(model.GroupTrees.ConvertToINodeArray(groupList), model.GroupTrees.ConvertToINodeArray(groupAll), 2)
	ids := make([]int64, 0, len(list))
	for _, v := range list {
		ids = append(ids, v.GetId())
	}
	// 查询设备
	m := svc.Dao.TAuthGroupStation
	return m.GetByIds(ids)
}

// AddStations 新增设备.
func (l *StationLogic) AddStations() {

}

// GetStationIds 获取用户关联的站点ID.
func (l *StationLogic) GetStationIds(userId int64) ([]string, error) {
	// 判断用户是否有这个设备权限.
	redis := db.NewRedis()
	stationsAuthKey := fmt.Sprintf(db.KeyUserThingId+"#%v", userId)
	stationIds, _ := redis.Get(stationsAuthKey)
	if stationIds != "" {
		return strings.Split(stationIds, ","), nil
	}
	// 获取用户组.
	groupModel := svc.Dao.TAuthGroup
	groups, err := groupModel.GetUserGroup(userId)
	if err != nil {
		logger.Log.Errorf("CheckThingAuth userId:=%v, err:=%v", userId, err)
		return []string{}, err
	}
	groupIds := make([]int64, 0, len(groups))
	for index := range groups {
		groupIds = append(groupIds, groups[index].ID)
	}
	// 获取站点.
	stationsList, err := svc.Dao.TAuthGroupStation.GetByIds(groupIds)
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return []string{}, nil
	}
	if err != nil {
		return []string{}, err
	}
	strArr := make([]string, 0, len(stationsList))
	for _, v := range stationsList {
		strArr = append(strArr, v.StationId)
	}
	redis.Set(stationsAuthKey, strings.Join(strArr, ","), time.Hour*1)
	return strArr, nil
}

func (l *StationLogic) GetThingIdByStationIdAndModelId(stationId string, modelId string) (string, error) {
	// 查询设备ID
	key := fmt.Sprintf("getthingId:%s:%s", stationId, modelId)
	thingId, _ := db.NewRedis().Get(key)
	if thingId == "" {
		thingInfo, err := svc.Dao.TThingStation.WhereMapStation(map[string]string{"station_id": stationId, "model_id": modelId})
		if err != nil {
			return "", err
		}
		thingId = thingInfo.ThingID
		db.NewRedis().Set(key, thingId, time.Hour)
	}
	return thingId, nil
}
func (l *StationLogic) HomeData(stationId string, modelId string, requestId string) (utils.H, error) {
	attributes, ok := config.ConfJson.CurveJson[modelId] // 属性
	if !ok {
		return utils.H{}, nil
	}
	thingId, err := l.GetThingIdByStationIdAndModelId(stationId, modelId)
	if err != nil {
		return utils.H{}, err
	}
	resp := utils.H{}
	for index := range attributes {
		result, _ := cache.GetIntegralHourDatas(thingId, attributes[index], "", 0)
		Log.Log.Infof("[%s] cache.GetIntegralHourDatas:=%v", requestId, result)
		datas := utils.H{}
		keys := make([]string, 0, len(result))
		values := make([]interface{}, 0, len(attributes))
		for _, value := range result {
			datetime := time.Unix(value.InsertTime, 0).Format("2006/01/02 15:04:05")
			switch value.Type {
			case "float":
				keys = append(keys, datetime)
				values = append(values, value.FValue)
				//datas[datetime] = value.FValue
				break
			case "int":
				keys = append(keys, datetime)
				values = append(values, value.IValue)
				//datas[datetime] = value.IValue
				break
			case "string":
				keys = append(keys, datetime)
				values = append(values, value.SValue)
				//datas[datetime] = value.SValue
			}
		}
		if len(values) <= 0 {
			continue
		}
		datas["values"] = values
		datas["keys"] = keys
		resp[attributes[index]] = datas
		//resp = append(resp, utils.H{values[index]: datas})
	}
	return resp, nil
}
